#ifndef SESSIONMODEL_H
#define SESSIONMODEL_H

#include <QDateTime>
#include <QQmlListProperty>
#include <QSharedDataPointer>

#include "../../global/xnamespace.h"
#include "ContactModel.h"
#include "GroupModel.h"
#include "MessageListModel.h"

X_BEGIN_NAMESPACE

// 私有数据
class SessionModelPrivate : public QSharedData
{
public:
    SessionModelPrivate();

public:
    QString m_id;
    bool m_pinToTop;
    bool m_showInList;
    SessionType m_sessionType;
    MessageListModel m_messageList;

public:
    QObject* m_actualChatObject;        // 实际会话对象
};

/**
 * @class SessionModel
 *
 * 会话模型。会话有多种类型，作为一个客户端，它需要识别类型，并知道对象的ID。
 * 为了方便起见，会话的ID直接使用聊天对象的ID作为基础。
 *
 * P2P会话：会话ID是聊天对象的JID
 * 群组会话：会话ID是群组的ID
 */
class SessionModel : public QObject
{
    Q_OBJECT

    Q_PROPERTY(QString id READ id NOTIFY idChanged)
    Q_PROPERTY(X::SessionType sessionType READ sessionType WRITE setSessionType NOTIFY sessionTypeChanged)
    Q_PROPERTY(QString name READ name NOTIFY nameChanged)
    Q_PROPERTY(QString photo READ photo NOTIFY photoChanged)
    Q_PROPERTY(QString lastMessageContent READ lastMessageContent NOTIFY lastMessageContentChanged)
    Q_PROPERTY(X::MessageContentType lastMessageContentType READ lastMessageContentType NOTIFY lastMessageContentTypeChanged)
    Q_PROPERTY(QString lastSenderName READ lastSenderName NOTIFY lastSenderNameChanged)
    Q_PROPERTY(QString lastSenderJid READ lastSenderJid NOTIFY lastSenderJidChanged)
    Q_PROPERTY(QDateTime lastMessageTime READ lastMessageTime NOTIFY lastMessageTimeChanged)
    Q_PROPERTY(bool pinToTop READ pinToTop WRITE setPinToTop NOTIFY pinToTopChanged)
    Q_PROPERTY(bool showInList READ showInList WRITE setShowInList NOTIFY showInListChanged)

signals:
    void idChanged(QString id);
    void sessionTypeChanged(SessionType sessionType);
    void nameChanged(QString name);
    void photoChanged(QString photo);
    void lastMessageContentChanged(QString sessionId, QString lastMessageContent);
    void lastMessageContentTypeChanged(QString sessionId, MessageContentType lastMessageContentType);
    void lastSenderNameChanged(QString sessionId, QString lastSenderName);
    void lastSenderJidChanged(QString sessionId, QString lastSenderJid);
    void lastMessageTimeChanged(QString sessionId, QDateTime lastMessageTime);
    void pinToTopChanged(bool pinToTop);
    void showInListChanged(bool showInList);

public:
    SessionModel();
    SessionModel(const QString& id);
    SessionModel(const SessionModel& src);
    SessionModel &operator =(const SessionModel& rhs);

    static const char *qmlName();

public:
    // 使用非属性方式返回自定义类型列表时，可以使用QVariantList方式包装数据再给QML使用
    Q_INVOKABLE QVariant loadMessages(int startId, int count);
    Q_INVOKABLE void sendMessage(const QString& messageConent, X::MessageContentType messageConentType);
    Q_INVOKABLE void receivedMessage(const QString& senderJid, const QString& content, X::MessageContentType contentType, QDateTime stamp);

public:
    QString id() const;
    SessionType sessionType() const;
    QString name();
    QString photo();
    QString lastMessageContent() const;
    MessageContentType lastMessageContentType() const;
    QString lastSenderName() const;
    QString lastSenderJid() const;
    QDateTime lastMessageTime() const;
    bool pinToTop() const;
    bool showInList() const;

public slots:
    SessionModel& setSessionType(SessionType sessionType);
    SessionModel& setPinToTop(bool pinToTop);
    SessionModel& setShowInList(bool showInList);

private:
    MessageModel addMessage(int messageId,
                            const QString &senderJid,
                            const QString &content,
                            const QString &thumbnail,
                            MessageContentType contentType,
                            QDateTime time,
                            bool appendAtFront);
    const MessageModel* lastMessage() const;

    ContactModel *contact();
    GroupModel *group();

protected:
    QSharedDataPointer<SessionModelPrivate> d;

    static const int MAX_MESSAGE_COUNT = 200;
    static const char READ_MESSAGES[];
    static const char INSERT_MESSAGE[];
};

X_END_NAMESPACE

Q_DECLARE_METATYPE(X::SessionModel)
Q_DECLARE_METATYPE(X::MessageListModel)

#endif // SESSIONMODEL_H
